package com.wms.service.impl;

import com.alibaba.excel.EasyExcel;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.itextpdf.text.*;

import com.itextpdf.text.Font;
import com.itextpdf.text.pdf.BaseFont;
import com.itextpdf.text.pdf.PdfPCell;
import com.itextpdf.text.pdf.PdfPTable;
import com.itextpdf.text.pdf.PdfWriter;
import com.wms.bean.PageBean;
import com.wms.bean.ResultBean;
import com.wms.code.CodeFactory;
import com.wms.dto.AllocatedetailExcelDTO;
import com.wms.dto.AllocatetailQueryVo;
import com.wms.dto.AllocatetailSaveVo;
import com.wms.entity.Allocatedetail;
import com.wms.mapper.AllocatedetailMapper;

import com.wms.service.AllocatedetailService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.awt.*;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.net.URLEncoder;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

@Service
public class AllocatedetailServiceImpl implements AllocatedetailService {

    @Autowired
    private AllocatedetailMapper allocatetailMapper;

    //编码前缀
    String prefix = "DD"; // 可以更改为不同的前缀


    private final String IMAGE_URL = "/images/";
    // 允许的文件类型集合
    private static final Set<String> ALLOWED_EXTENSIONS = new HashSet<>();

    // 静态初始化允许的文件类型
    static {
        ALLOWED_EXTENSIONS.add("png");
        ALLOWED_EXTENSIONS.add("jsp");
    }
    @Override
    public PageBean<List<Allocatedetail>> query(AllocatetailQueryVo queryVo) {
        // 分页处理
        PageHelper.startPage(queryVo.getPage(), queryVo.getPageSize());
        // 条件查询
        List<Allocatedetail> list = allocatetailMapper.selectByCondition(queryVo);
        PageInfo<Allocatedetail> pageInfo = new PageInfo<>(list);
        // 封装分页结果
        return new PageBean<>(
                queryVo.getPage(),
                queryVo.getPageSize(),
                pageInfo.getTotal(),
                pageInfo.getList()
        );
    }

    @Override
    public int save(AllocatetailSaveVo saveVo) {
        String maxCode = allocatetailMapper.selectMaxCode();
        saveVo.setCode(CodeFactory.createArrivalCode(maxCode,prefix));
        return allocatetailMapper.insert(saveVo);
    }

    @Override
    public int update(AllocatetailSaveVo saveVo) {
        return allocatetailMapper.updateById(saveVo);
    }

    @Override
    public int remove(Integer id) {
        return allocatetailMapper.updateStatus(id);
    }

    @Override
    public int removePhysics(Integer id) {
        return allocatetailMapper.deleteById(id);
    }

    /**
     * 图片上传业务
     * @param file
     * @return
     */
    @Override
    public String toUpload(MultipartFile file, HttpServletRequest request) {
        return Upload(file,request);
    }
    /**
     * 实现文件上传 返回上传后 文件在服务器上的相对路径
     *
     * @param file
     * @return
     */
    String Upload(MultipartFile file, HttpServletRequest request) {
        // 1. 检查文件是否为空
        if (file.isEmpty()) {
            return "";
        }

        // 2. 验证文件类型
        String fileExtension = getFileExtension(file);
        if (!ALLOWED_EXTENSIONS.contains(fileExtension.toLowerCase())) {
            return "";
        }


        //获取新的文件名
        String newFileName = getNewFileName(file);

        //获取文件在服务器上的存储目录
        String root = request.getServletContext().getRealPath("/");

        //需求 将每日上传的图片 放到同一日期目录下
        String ymd=getYMD();

        File dir = new File(root + IMAGE_URL+ymd+"/");
        if (!dir.exists())
            dir.mkdirs();//创建目录
        //将file文件 写入到指定目录 下
        try {
            file.transferTo(new File(root + IMAGE_URL+ymd+"/", newFileName));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        return IMAGE_URL+ymd+"/" + newFileName;
    }

    /**
     * 获取文件扩展名
     */
    private String getFileExtension(MultipartFile file) {
        String fileName = file.getOriginalFilename();
        if (fileName == null || !fileName.contains(".")) {
            throw new RuntimeException("文件名称格式不正确");
        }
        return fileName.substring(fileName.lastIndexOf(".") + 1);
    }


    /**
     * 获取系统时间 yyyyMMdd
     * @return
     */
    String getYMD() {
        //获取年月日时间
        LocalDate localDate = LocalDate.now();
        //将日期转换成字符串format将日期格式化成字符串
        return localDate.format(DateTimeFormatter.ofPattern("yyyyMMdd"));
    }
    /**
     * 获取新的文件名
     *
     * @param file
     * @return
     */
    String getNewFileName(MultipartFile file) {
        //获取原始文件名  通过前端传的文本文件获取原始文件名
        String fileName = file.getOriginalFilename();
        //获取文件后缀  通过分割获取员文件的后缀
        String[] tmp = fileName.split("[.]");
        int len = tmp.length;
        //新的文件名   通过下标获取最后一位元素，保证获取的一定是后缀名，而不是名字的元素
        String newFileName = System.currentTimeMillis() + "." + tmp[len - 1];
        return newFileName;
    }



    /**
     * 生成调拨单详情PDF
     */
    @Override
    public void generatePrintPdf(AllocatetailQueryVo queryVo, HttpServletResponse response) throws Exception {
        // 1. 查询所有符合条件的调拨单详情（不分页）
        queryVo.setPage(1);
        queryVo.setPageSize(Integer.MAX_VALUE);
        PageBean<List<Allocatedetail>> pageBean = this.query(queryVo);
        List<Allocatedetail> details = pageBean.getList();

        // 2. 设置响应参数
        response.setContentType("application/pdf");
        String fileName = URLEncoder.encode("调拨单详情打印.pdf", "UTF-8");
        response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + "\"");

        // 3. 初始化PDF文档
        Document document = new Document(PageSize.A4);
        OutputStream os = response.getOutputStream();
        PdfWriter.getInstance(document, os);
        document.open();

        // 4. 配置中文字体（解决中文显示问题）
        BaseFont bfChinese = BaseFont.createFont("STSong-Light", "UniGB-UCS2-H", BaseFont.NOT_EMBEDDED);
        Font titleFont = new Font(bfChinese, 16, Font.BOLD);
        Font contentFont = new Font(bfChinese, 12, Font.NORMAL);
        Font smallFont = new Font(bfChinese, 10, Font.NORMAL);

        // 5. 添加标题和基本信息
        Paragraph title = new Paragraph("调拨单详情", titleFont);
        title.setAlignment(Element.ALIGN_CENTER);
        document.add(title);
        document.add(Chunk.NEWLINE); // 换行

        // 6. 添加表格数据（根据数据库字段调整列数和内容）
        PdfPTable table = new PdfPTable(9); // 9列（包含周转筐字段）
        table.setWidthPercentage(100);
        table.setSpacingBefore(10f);

        // 表头
        String[] headers = {"物品编码", "物品名称", "可用库存", "申请数量", "审批数量", "已出库数量", "周转筐", "计量单位", "单价"};
        for (String header : headers) {
            PdfPCell cell = new PdfPCell(new Phrase(header, contentFont));
            cell.setHorizontalAlignment(Element.ALIGN_CENTER);
            cell.setPadding(5f);
            table.addCell(cell);
        }

        // 表内容
        if (details != null && !details.isEmpty()) {
            for (Allocatedetail detail : details) {
                table.addCell(createCell(detail.getCode(), contentFont));
                table.addCell(createCell(detail.getName(), contentFont));
                table.addCell(createCell(detail.getAvailableStock() == null ? "" : detail.getAvailableStock().toString(), contentFont));
                table.addCell(createCell(detail.getApplyNum() == null ? "" : detail.getApplyNum().toString(), contentFont));
                table.addCell(createCell(detail.getAuditNum() == null ? "" : detail.getAuditNum().toString(), contentFont));
                table.addCell(createCell(detail.getOutNum() == null ? "" : detail.getOutNum().toString(), contentFont));
                table.addCell(createCell(detail.getBox(), contentFont));
                table.addCell(createCell(detail.getUnit(), contentFont));
                table.addCell(createCell(detail.getPrice(), contentFont));
            }
        } else {
            // 无数据时显示提示
            PdfPCell emptyCell = new PdfPCell(new Phrase("暂无数据", smallFont));
            emptyCell.setColspan(9); // 跨所有列
            emptyCell.setHorizontalAlignment(Element.ALIGN_CENTER);
            table.addCell(emptyCell);
        }

        document.add(table);
        document.close();
        os.close();
    }

    /**
     * 创建表格单元格（封装重复逻辑）
     */
    private PdfPCell createCell(String content, Font font) {
        PdfPCell cell = new PdfPCell(new Phrase(content == null ? "" : content, font));
        cell.setHorizontalAlignment(Element.ALIGN_CENTER);
        cell.setPadding(5f);
        return cell;
    }


    @Override
    public void generateExcel(HttpServletResponse response, List<Allocatedetail> detailList) throws IOException {
        // 1. 数据转换（Allocatedetail -> ExcelDTO）
        List<AllocatedetailExcelDTO> excelDTOList = new ArrayList<>();
        for (int i = 0; i < detailList.size(); i++) {
            Allocatedetail detail = detailList.get(i);
            AllocatedetailExcelDTO dto = new AllocatedetailExcelDTO();
            dto.setSerialNumber(i + 1);
            dto.setCode(detail.getCode());
            dto.setName(detail.getName());
            dto.setAvailableStock(detail.getAvailableStock());
            dto.setApplyNum(detail.getApplyNum());
            dto.setAuditNum(detail.getAuditNum());
            dto.setOutNum(detail.getOutNum());
            dto.setBox(detail.getBox());
            dto.setUnit(detail.getUnit());
            dto.setPrice(detail.getPrice());
            excelDTOList.add(dto);
        }

        // 2. 关键：设置响应头，确保浏览器自动下载
        // 解决中文文件名乱码问题
        String fileName = URLEncoder.encode("调拨单详情", "UTF-8").replaceAll("\\+", "%20");
        // 设置内容类型为Excel
        response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        // 设置字符编码
        response.setCharacterEncoding("UTF-8");
        // 触发下载的核心响应头
        response.setHeader("Content-Disposition", "attachment;filename*=UTF-8''" + fileName + ".xlsx");
        // 防止缓存
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");

        // 3. EasyExcel写入响应流
        EasyExcel.write(response.getOutputStream(), AllocatedetailExcelDTO.class)
                .sheet("调拨单详情")
                .doWrite(excelDTOList);
    }
}
